<?php

namespace app\common\service;

use think\Db;
use think\Cache;

use addons\epay\library\Service;
use addons\third\model\Third;
use app\common\model\User;
use app\common\model\MoneyLog;
use app\common\model\ads\Order as AdOrderModel;
use app\common\model\ads\Ad as AdModel;
use app\common\model\printmanager\Order as PrintOrderModel;
use app\common\model\huntermanager\Hunter;

class Payment
{

    const THIRD_TRADE_INFO_KEY = "third_pay_order_";

    /**
     * 获取广告订单支付信息
     */
    public static function getAdOrder($adId = 0, $order_no = '', $user_id = null, $platform = "wechat", $method = "miniapp")
    {
        if ($adId) {
            $order = AdOrderModel::createOrder($adId);
        } else {
            $order = AdOrderModel::where([
                'order_no' => $order_no
            ])->find();
        }

        if (!$order) {
            throw new \Exception('订单不存在');
        }

        if ($order->status == 1) {
            throw new \Exception('订单已支付');
        }

        $res = [
            'order' => $order,
            'payment' => ''
        ];


        // 未支付的返回支付请求信息
        $hash = self::THIRD_TRADE_INFO_KEY . $order->order_no;
        $cache = Cache::get($hash);
        if ($cache) {
            $res['payment'] = $cache;
        } else {

            $openId = '';

            if ($platform == 'wechat' && in_array($method, ['miniapp', 'mp', 'app'])) {

                if (!$user_id) {
                    $user_id = $order->user_id;
                }

                $openId = $openId = self::getOpenId($user_id, $method);
            }

            $payment = self::createOrderPay($order, '赏金发布费用', $openId, $platform, $method);

            Cache::set($hash, $payment, 60);

            $res['payment'] = $payment;
        }

        $res['payment'] = is_array($res['payment']) ? $res['payment'] : json_decode($res['payment'], 1);

        return $res;
    }


    /**
     * 获取印刷品订单支付信息
     */
    public static function getPrintOrder($order_no, $user_id = null, $platform = "wechat", $method = "miniapp")
    {
        $order = PrintOrderModel::where([
            'order_no' => $order_no
        ])->find();

        if (!$order) {
            throw new \Exception('订单不存在');
        }

        $res = [
            'order' => $order,
            'payment' => ''
        ];

        if ($order->status == 1) {
            throw new \Exception('订单已支付');
        }

        // 未支付的返回支付请求信息
        $hash = self::THIRD_TRADE_INFO_KEY . $order->order_no;
        $cache = Cache::get($hash);
        if ($cache) {
            $res['payment'] = $cache;
        } else {

            $openId = '';

            if ($platform == 'wechat' && in_array($method, ['miniapp', 'mp', 'app'])) {

                if (!$user_id) {
                    $user_id = $order->user_id;
                }
                $openId = self::getOpenId($user_id, $method);
            }

            $payment = self::createOrderPay($order, '印刷品', $openId, $platform, $method);
            Cache::set($hash, $payment, 60);
            $res['payment'] = $payment;
        }
        $res['payment'] = is_array($res['payment']) ? $res['payment'] : json_decode($res['payment'], 1);
        return $res;
    }

    /**
     * 订单完成支付
     */
    public static function paydoneOrder($orderData)
    {

        $order_no = isset($orderData['order_no']) ? self::getOriginOrderNo($orderData['order_no']) : '';

        $order_prefix = self::getOrderPrefix($order_no);

        $orderData['order_no'] = $order_no;
        if ("AD" == $order_prefix) {
            // 广告订单
            return self::adOrderDone($orderData);
        } elseif ("HB" == $order_prefix) {
            // 印刷品订单
            return self::printOrderDone($orderData);
        }

        throw new \Exception('Unknown Order');
    }

    /**
     * 印刷订单支付完成
     */
    public static function printOrderDone($data)
    {
        $order = PrintOrderModel::where('order_no', $data['order_no'])->find();
        if (!$order) {
            throw new \Exception('Print Order does not exists');
        }
        if ($order->status == 1) {
            return true;
        }

        $order->status = 1;
        $order->paytime = time();
        $order->third_order_no = isset($data['third_order_no']) ? $data['third_order_no'] : '';

        $res = $order->save();

        // 给上级相应奖励
        Hunter::rewardForPrinter($order);

        \app\common\model\score\Task::execute_task(8, $order->user_id);
        \app\common\model\score\Task::execute_task(19, $order->user_id);

        return $res === false ? false : true;
    }

    /**
     * 广告订单支付完成
     */
    public static function adOrderDone($data)
    {
        $order = AdOrderModel::where('order_no', $data['order_no'])->find();
        if (!$order) {
            throw new \Exception('Ad Order does not exists');
        }
        if ($order->status == 1) {
            return true;
        }

        $order->status = 1;
        $order->paytime = time();
        $order->third_order_no = isset($data['third_order_no']) ? $data['third_order_no'] : '';

        $res = $order->save();
        if(!$res){
            return false;
        }

        #修改广告的各种到期时间
        $ad = AdModel::find($order->ad_id);

        if(!$ad){
            return false;
        }

        $now = time();

        if($ad->effecttime){
            $ad->effecttime = $now + $ad->effecttime_day * 86400;
        }

        if($ad->toptime){
            $ad->toptime = $now + $ad->toptime_day * 86400;
        }

        if($ad->recommendtime){
            $ad->recommendtime = $now + $ad->recommendtime_day * 86400;
        }

        $ad->save();

        // 给上级相应奖励
        Hunter::rewardForAds($order);
        \app\common\model\score\Task::execute_task(6, $ad->user_id);
        \app\common\model\score\Task::execute_task(10, $ad->user_id);
        return $res === false ? false : true;
    }

    /**
     * 印刷订单关闭
     */
    public static function printOrderClose(PrintOrderModel $order)
    {

        if ($order->status == 4) {
            return true;
        }

        if ($order->status != 0) {
            throw new \Exception('订单状态错误');
        }

        $order->status = 4;

        $res = $order->save();


        if($res && $order->gold_num > 0){
            // 退回金币
            User::money($order->gold_num, $order->user_id, '订单关闭，金币退回');
        }

        return $res === false ? false : true;
    }
    
    /**
     * 获取微信openid
     */
    protected static function getOpenId($user_id, $method)
    {
        $platconf = [
            'miniapp' => 'wxapp'
        ];

        $whereQr = isset($platconf[$method]) ? $platconf[$method] : 'wxapp';
        $third = Third::where('user_id', $user_id)->where('platform', $whereQr)->find();

        if (!$third) {
            throw new \Exception('未找到用户openid数据');
        }

        return $third->openid;
    }

    /**
     * 生成请求支付信息【每一次都不一样，生成唯一的订单号】
     */
    public static function createOrderPay($order, $tradeTitle, $openId, $platform = "wechat", $method = "miniapp")
    {

        $payment = Service::submitOrder([
            'amount'    => $order->real_amount,
            'orderid'   => self::uniqueOrderNo($order->order_no),
            'type'      => $platform,
            'title'     => $tradeTitle,
            'notifyurl' => request()->root(true) . '/addons/epay/api/notifyx/type/' . $platform,
            'returnurl' => "",
            'method'    => $method,
            'openid'    => $openId
        ]);

        if (!$payment) {
            throw new \Exception('订单创建失败');
        }

        return $payment;
    }

    /**
     * 退款[只支持广告订单]
     */
    public static function refundAdOrder(AdOrderModel $order, $refundAmoun = null, $remark = '')
    {

        $amount = $refundAmoun ? $refundAmoun : $order->real_amount;
        $refund = Service::refundWxpay($order->third_order_no, $order->real_amount, $amount , 'REFUND'.$order->order_no, $remark );

        if (!$refund || $refund['trade_status'] != 'SUCCESS') {
            $msg = isset($refund['trade_status']) ? $refund['trade_status'] : '原因未知';
            throw new \Exception("订单退款失败：{$msg}");
        }

        $order->status = 2;

        $order->save();

        doLog([
            "order_id" => $order->id,
            "third_order_no" => $order->third_order_no,
            "amount" => $amount,
            "remark" => $remark,
        ],'refund');

        return true;
    }

    /**
     * 获取订单前缀【业务识别】已经转大写
     */
    public static function getOrderPrefix($order_no)
    {
        return strtoupper(substr($order_no, 0, 2));
    }


    /**
     * 对原order_no生成唯一的订单号【尾巴加时间戳】
     */
    public static function uniqueOrderNo($order_no = '')
    {
        return $order_no . time();
    }

    /**
     * 对异步通知来的唯一的订单号【尾巴去除时间戳】
     */
    public static function getOriginOrderNo($order_no = '')
    {
        return substr($order_no, 0, -10);
    }
}
